﻿using HslCommunication.ModBus;
using HslCommunication;
using System;
using System.Threading;
using SuperMicroWave.Common;
using System.Runtime.InteropServices;
using SuperMicroWave.LogFile;

namespace SuperMicroWave.Modbus
{
    public class ModbusTcp
    {
        public ushort hRegDataSize = (ushort)(Marshal.SizeOf(typeof(ConnectInfo.HRegData)) / 2);

        private ModbusTcpNet? _modbusTcpNet;
        private OperateResult? _ModBusMsg;
  
        public ModbusTcp()
        {
            ThreadStart threadStart = ReadRegThread;
            Thread thread = new Thread(threadStart);
            thread.IsBackground = true;
            thread.Start();

            ThreadStart threadStart1 = ReadRegThread1;
            Thread thread1 = new Thread(threadStart1);
            thread1.IsBackground = true;
            thread1.Start();
        }

        /// <summary>
        /// 重新连接
        /// </summary>
        public void ReConnect()
        {
            DisConnect();
            //ConnectModbusTcp("127.0.0.1", 502, (byte)1);
            ConnectModbusTcp("172.17.18.5", 502, (byte)1);
        }

        /// <summary>
        /// 连接服务器
        /// </summary>
        public void ConnectModbusTcp(string strAddr, int nPort, byte Slave)
        {
            _modbusTcpNet = new ModbusTcpNet(strAddr, nPort, Slave);
            _modbusTcpNet.ConnectTimeOut = 1000;
            _modbusTcpNet.ReceiveTimeOut = 1000;
            _ModBusMsg = _modbusTcpNet.ConnectServer();
        }

        /// <summary>
        /// 是否连接成功
        /// </summary>
        public bool IsConnected()
        {
            return _ModBusMsg != null && _ModBusMsg.IsSuccess;
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public void DisConnect()
        {
            _modbusTcpNet?.ConnectClose();
            _modbusTcpNet?.Dispose();
            _modbusTcpNet = null;
            _ModBusMsg = null;
        }

        /// <summary>
        /// 读寄存器
        /// </summary>
        public void ReadRegThread()
        {
            while (true)
            {
                if (IsConnected())
                {
                    OperateResult<byte[]> recv1 = _modbusTcpNet!.Read("0", hRegDataSize);
                    if (!recv1.IsSuccess)
                    {
                        LogHelper.WriteErrLog("读寄存器失败：" + recv1.Message);
                        DisConnect();  
                        Thread.Sleep(1000);
                        continue;
                    }
                    ConnectHelper.Conversion(recv1.Content);
                    GlobalValue.hRegData = (ConnectInfo.HRegData)ConnectHelper.BytesToStruct(recv1.Content, typeof(ConnectInfo.HRegData));

                    GlobalValue.NowState.T = (double)GlobalValue.hRegData.R7 / 100;
                    GlobalValue.NowState.T1 = (double)GlobalValue.hRegData.R8 / 100;
                    GlobalValue.NowState.P1 = Math.Round(GlobalValue.hRegData.R6 * 3.3 / 4095 * 2 * 20 / 5, 2);
                    GlobalValue.NowState.P2 = (double)GlobalValue.hRegData.R0 * 1530 / 3600;
                }
                else
                {
                    ReConnect();
                }
                Thread.Sleep(1000);
            }
        }

        /// <summary>
        /// 读升温控制状态寄存器
        /// </summary>
        public void ReadRegThread1()
        {
            while(true)
            {
                if (IsConnected())
                {
                    ushort[]? temp = ReadRegister("65", 1);
                    ushort curState = temp == null ? (ushort)2 : temp[0];
                    switch(curState)
                    {
                        case 0:
                            GlobalValue.NowState.CurState = ConnectInfo.InsState.DEV_IDLE;
                            break;
                        case 1:
                            GlobalValue.NowState.CurState = ConnectInfo.InsState.DEV_HEAT;
                            break;
                        case 0xff:
                            GlobalValue.NowState.CurState = ConnectInfo.InsState.DEV_PAUSE;
                            break;
                        case 2:
                            GlobalValue.NowState.CurState = ConnectInfo.InsState.DEV_ERROR;
                            break;
                    }
                }
                Thread.Sleep(100);
            }
        }

        public bool[]? ReadCoils(string addr, ushort length)
        {
            if (IsConnected())
            {
                OperateResult<bool[]> read = _modbusTcpNet!.ReadCoil(addr, length);
                if (!read.IsSuccess)
                {
                    return null;
                }
                else
                    return read.Content;
            }
            return null;
        }

        public bool[]? ReadDis(string addr, ushort length)
        {
            if (IsConnected())
            {
                OperateResult<bool[]> read = _modbusTcpNet!.ReadDiscrete(addr, length);
                if (!read.IsSuccess)
                {
                    return null;
                }
                else
                    return read.Content;
            }
            return null;
        }

        public ushort[]? ReadRegister(string addr, ushort size)
        {
            if (IsConnected())
            {
                OperateResult<byte[]> recv = _modbusTcpNet!.Read(addr, size);
                if (!recv.IsSuccess)
                    return null;
                ConnectHelper.Conversion(recv.Content);
                return ConnectHelper.BytesToUShort(recv.Content);
            }
            return null;
        }

        public void WriteRegister(string addr, ushort value)
        {
            if (IsConnected())
            {
                byte[] temp = BitConverter.GetBytes(value);
                ConnectHelper.Conversion(temp);
                OperateResult send = _modbusTcpNet!.Write(addr, temp);
                if (!send.IsSuccess)
                    LogHelper.WriteInfoLog($"写寄存器[{addr}]失败：" + send.Message);
            }
        }

        public void WriteCoil(string addr, bool value)
        {
            if (IsConnected())
            {
                OperateResult send = _modbusTcpNet!.Write(addr, value);
                if (!send.IsSuccess)
                    LogHelper.WriteInfoLog($"写线圈[{addr}]失败：" + send.Message);
            }
        }
    }
}
